'''
Created on May 30, 2012

@author: byron
'''
from serial import Serial
from serial.serialutil import SerialException
from serial.serialutil import SerialTimeoutException
import  time
import  thread
import  wx.lib.newevent


(SerialConnectEvent, EVT_CONNECT_SERIAL) = wx.lib.newevent.NewEvent()
(SerialDisconnectEvent, EVT_DISCONNECT_SERIAL) = wx.lib.newevent.NewEvent()
(SerialDataEvent, EVT_SERIAL_DATA) = wx.lib.newevent.NewEvent()
(SerialErrorEvent, EVT_SERIAL_ERROR) = wx.lib.newevent.NewEvent()


class Regulator:  

    def __init__(self, win, port, baudrate, timeout):  
        self.win = win             
        self.port = port
        self.baudrate = baudrate
        self.timeout = timeout
        self.connected = False
        
        self.current_temp = 0
        self.current_humidity = 0
        
        self.fan_status = False
        self.heater_status = False
        self.light_status = False
        self.pump_status = False
        
        self.Connect()
        
    def Connect(self):        
        self.RegThread = RegulatorThread(self)
        
        try:
            self.conn = Serial(port=self.port, baudrate=9600, timeout=5)
            self.conn.readlines()            
            self.RegThread.Start() 
            self.win.logger.Log('INFO', 'Connected.') 
        except SerialException as e:
            wx.PostEvent(self.win, SerialErrorEvent(error=e))
            #wx.MessageBox('Connection Error: {0}'.format(e), 'Error', wx.OK | wx.ICON_ERROR)
    
    def Disconnect(self):
        if self.conn:
            self.RegThread.Stop()
            self.conn.close()
            self.win.logger.Log('INFO', 'Disconnected.') 
            
    
    def Command(self, cmd):
        try:
            self.conn.write(cmd)
            return self.conn.readline().strip()
        except (SerialException, SerialTimeoutException) as e:
            wx.PostEvent(self.win, SerialErrorEvent(error=e))
            return '0'
        
    def GetTemperature(self,):
        try:
            val = self.Command('T')
            tmp = float(val)
        except ValueError:
            #self.win.logger.Log('WARNING', 'invalid temperature: \"%s\"' % str(val)) 
            tmp = 0 
            
        self.current_temp = tmp
        return self.current_temp
    
    def GetHumidity(self):
        try:
            val = self.Command('H')
            hum = float(val)
        except ValueError:
            #self.win.logger.Log('WARNING', 'invalid humidity: \"%s\"' % str(val))
            hum = 0 

        self.current_humidity = hum
        return self.current_humidity
    
    def FanStatus(self):
        value = self.Command('q')
        self.fan_status = True if 'On' == value else False
        return self.fan_status
    
    def HeaterStatus(self):
        value = self.Command('w')
        self.heater_status = True if 'On' == value else False
        return self.heater_status
        
    def PumpStatus(self):
        value = self.Command('r')
        self.pump_status = True if 'On' == value else False
        return self.pump_status
        
    def LightStatus(self):
        value = self.Command('e')
        self.light_status = True if 'On' == value else False
        return self.light_status
        
    def OnFan(self):
        if False == self.fan_status:
            self.conn.write('f')
            self.win.logger.Log('INFO', 'Fan turned on.')
            self.fan_status = True
        
    def OffFan(self):
        if True == self.fan_status:
            self.conn.write('1')
            self.win.logger.Log('INFO', 'Fan turned off.')
            self.fan_status = False  
    
    def OnHeater(self):
        if False == self.heater_status:
            self.conn.write('h')
            self.win.logger.Log('INFO', 'Heater turned on')
            self.heater_status = True
        
    def OffHeater(self):
        if True == self.heater_status:
            self.conn.write('2')
            self.win.logger.Log('INFO', 'Heater turned off')
            self.heater_status = False
        
    def OnLight(self):
        if False == self.light_status:
            self.conn.write('l')
            self.win.logger.Log('INFO', 'Light turned on')
            self.light_status = True 

    def OffLight(self):
        if True == self.light_status:
            self.conn.write('3')
            self.win.logger.Log('INFO', 'Light turned off')
            self.light_status = False 
    
    def OnPump(self):
        if False == self.pump_status:
            self.conn.write('p')
            self.win.logger.Log('INFO', 'Pump turned on')
            self.pump_status = True 
    
    def OffPump(self):
        if True == self.pump_status:
            self.conn.write('4')
            self.win.logger.Log('INFO', 'Pump turned off')
            self.pump_status = False 


class RegulatorThread:
    
    def __init__(self, reg):
        self.win = reg.win
        self.reg = reg
        
    def Start(self):
        self.keepGoing = self.running = True
        thread.start_new_thread(self.Run, ())

    def Stop(self):
        self.keepGoing = False

    def IsRunning(self):
        return self.running

    def Run(self):
        while self.keepGoing:
            
            self.reg.GetTemperature()
            self.reg.GetHumidity()
            self.reg.FanStatus()
            self.reg.HeaterStatus()                          
            self.reg.LightStatus()
            self.reg.PumpStatus()

            wx.PostEvent(self.win, SerialDataEvent())
            time.sleep(1) #TODO make this adjustable in the settings

        self.running = False
    
    def Close(self):
        self.conn.Close()
    
        